
import Jama.Matrix;
public class Main 
{
	private double[][][] gibensmatrixmatrix = new double[100][100][100];
	private int gcount = 0;
	private final double TOLERANCE = 1 ^(-8);
	//static MatrixLibraries lib = new MatrixLibraries();
	public static void main(String[]args)
	{
		double[][] x = {{1,2,3},{2,1,2},{3,2,1}};
		Matrix X = new Matrix(x);
		double[][] y = {{1,2,3},{2,1,2},{3,2,1}};
		Matrix Y = new Matrix(y);
		double[][] product = (X.times(Y)).getArray();
		for(int i = 0; i < 3; i++)
		{
			System.out.println();
			for (int j = 0; j < 3; j++)
			{
				System.out.print(product[i][j] + ", ");				
			}
		}
		
		//declare here the inside brackets are the columns
	}
	//calls QR helper to find the eigenvalues of x prints them and returns the eigenvectors
	
	public double[][] QRmethod(double[][] x)
	{
		int size = x.length;
		double[][] eigenmatrix = QRhelper(x);
		
		double[] eigenvalues = new double[size];
		double[] eigenvector;
		for(int i = 0; i < size; i++)
		{
			eigenvalues[i] = eigenmatrix[i][i];
		}
		eigenmatrix = new double[size][size];
		for(int i = 0; i < size; i++)
		{
			eigenvector = findeigenvector(x, eigenvalues[i]);
			for(int j = 0; j < size; j++)
			{
				eigenmatrix[i][j] = eigenvector[j];
			}
		}
		
		System.out.println("Eigenvalues:");
		System.out.println(eigenvalues[0] + ", ");
		for (int i = 1; i < size; i++)
		{
			if(i != (size - 1))
			System.out.print(eigenvalues[i] + ", ");
			else
			System.out.print(eigenvalues[i]);
		}
		System.out.println("");
		return eigenmatrix;
	}
	public double[] findeigenvector(double[][] x, double e)
	{
		return null;
	}
	//calls upon gibens method to find QR
	// the finds the RQ matrix and checks if it is upper triangular
	//if it is it returns it otherwise it takes the new x(RQ) and recurs until it gets an upper triangular;
	
	public double[][] QRhelper(double[][] x)
	{
		int size = x.length;
		
		double[][] R = new double[size][size];
		double[][] Q = new double[size][size];
		double[][] temp = new double[size][size];
		R = gibens(x);
		for (int i = 0; i < size; i++)
		{
			for(int j = 0; j < size; j++)
			{
				Q[i][j] = gibensmatrixmatrix[0][i][j];
			}
		}
		Q = mmultiply(Q,x);
		for(int n = 1; n< gcount; n++)
		{
			for (int i = 0; i < size; i++)
			{
				for(int j = 0; j < size; j++)
				{
					temp[i][j] = gibensmatrixmatrix[n][i][j];
				}
			}
			Q = mmultiply(temp, Q);
		}
		x = mmultiply(R,Q);
		gcount = 0;
		boolean done = true;
		for(int i = 0; i < size; i++)
		{
			for(int j = 0; j < i; j++)
			{
				if(x[i][j] > TOLERANCE)
				{
					i = size;
					j = i;
					done = false;
				}
			}
		}
		if(done)
		{
			return x;
		}
		else
		{
			return QRhelper(x);
		}
	}
	
	// does gibens rotations recusivly until it gets R
	// returns R and stores all gibens rotations in gibensmatrixmatrix
	public double[][] gibens(double[][] x)
	{
		int size = x.length;
		int nOne = 0,nTwo = 0;;
		double c, s;
		for (int i = 1; i < size; i++)
		{
			for (int k = 0; k < i; k++)
			{
				if(x[i][k] != 0)
				{
					nOne = i;
					nTwo = k;
					i = size;
					k = i;
				}
			}
		}
		if (nOne == 0 && nTwo == 0)
		{
			return x;
		}
		c = (x[nOne][nOne])/(Math.sqrt((x[nOne][nOne] * x[nOne][nOne]) + (x[nOne][nTwo] * x[nOne][nTwo])));
		s = (-x[nOne][nTwo])/(Math.sqrt((x[nOne][nOne] * x[nOne][nOne]) + (x[nOne][nTwo] * x[nOne][nTwo])));
		double[][] g = new double[size][size];
		for (int i = 0; i < size; i++)
		{
			g[i][i]= 1;
		}
		g[nOne][nOne]= c;
		g[nTwo][nTwo] = c;
		g[nOne][nTwo] = s;
		g[nTwo][nOne] = -s;
		
		for (int i = 0; i < size; i++)
		{
			for(int k = 0; k < size; k++)
			{
				gibensmatrixmatrix[gcount][i][k] = g[i][k];
			}
		}
		gcount++;
		return gibens(mmultiply(g,x));
		
		
	}
	
	double[][] mmultiply(double[][] a, double[][] b)
	{
		return null;
	}
	double[][] mtransverse(double[][] x)
	{
		return null;
	}
	
	

}
